const fsExtend = MixlyUrl.BOARD_CONFIG.thirdPartyBoard ? require('../../common/modules/mixlyClient/fsExtend.js') : require('../common/modules/mixlyClient/fsExtend.js');
var arduinoShell = null;

var MixlyArduino = {};
MixlyArduino.compiling = false;
MixlyArduino.uploading = false;

MixlyArduino.binFilePath = "";

MixlyArduino.arduinoCliPath = MixlyEnv.clientPath + "/arduino-cli";

// 检测默认路径下是否有arduino-cli可执行文件，如果没有，则使用配置文件中所提供的arduino-cli路径
try {
    if (MixlyEnv.currentPlatform == "win32") {
        nodeFs.statSync(MixlyArduino.arduinoCliPath + "/arduino-cli.exe").isFile();
    } else {
        nodeFs.statSync(MixlyArduino.arduinoCliPath + "/arduino-cli").isFile();
    }
} catch (e) {
    try {
        let defaultPath = MixlyUrl.BOARD_CONFIG?.software?.defaultPath[MixlyEnv.currentPlatform] ?? undefined;
        // 判断配置文件中是否具有arduino-cli路径
        if (defaultPath?.arduinoCli) {
            MixlyArduino.arduinoCliPath = path.resolve(MixlyEnv.clientPath, defaultPath.arduinoCli);
        }
    } catch (e) {
        console.log(e);
    }

    if (MixlyArduino.arduinoCliPath != MixlyEnv.clientPath + "/arduino-cli") {
        try {
            MixlyArduino.arduinoCliPath = path.resolve(MixlyArduino.arduinoCliPath, "../").replace(/\\/g, "/");
        } catch (e) {
            MixlyArduino.arduinoCliPath = path.resolve(MixlyArduino.arduinoCliPath, "../");
        }
    }
}

var handleHWDir = function (path) {
    let jsonPath = MixlyArduino.arduinoCliPath + "/Arduino15/";
    let packagePath = jsonPath + "/packages/";
    let hardwarePath = path + "/hardware/";
    if (fsExtend.isdir(hardwarePath)) {
        let nameArr = fsExtend.getDirAndFileName(hardwarePath);
        if (!nameArr) return;
        let newDelPath = {};
        newDelPath.file = {};
        newDelPath.dir = {};
        newDelPath.file.path = jsonPath;
        newDelPath.dir.path = packagePath;
        newDelPath.file.name = nameArr[0];
        newDelPath.dir.name = nameArr[1];
        try {
            let newDelPathStr = JSON.stringify(newDelPath);
            nodeFs.writeFileSync(path + "/path.json", newDelPathStr);
        } catch(e) {
            console.log(e);
        }
        fsExtend.deldirWithName(packagePath, nameArr[1]);
        fsExtend.cpfileWithName(hardwarePath, jsonPath, nameArr[0]);
        fsExtend.cpdirWithName(hardwarePath, packagePath, nameArr[1], function () {
            fsExtend.deldir(hardwarePath);
        });
    }
}

MixlyArduino.configFileData = `
board_manager:
  additional_urls: [
    https://arduino.esp8266.com/stable/package_esp8266com_index.json,
    https://dl.espressif.com/dl/package_esp32_index.json,
    http://dan.drown.org/stm32duino/package_STM32duino_index.json
  ]
daemon:
  port: "50051"
directories:
  data: ${MixlyArduino.arduinoCliPath}/Arduino15
  downloads: ${MixlyArduino.arduinoCliPath}/staging
  user: ${MixlyArduino.arduinoCliPath}/Arduino
library:
  enable_unsafe_install: false
logging:
  file: ""
  format: text
  level: info
metrics:
  addr: :9090
  enabled: true
sketch:
  always_export_binaries: false
`;

nodeFs.writeFile(MixlyArduino.arduinoCliPath + "/arduino-cli.yaml", MixlyArduino.configFileData, 'utf8', function (err) {
    if (err) {
        MixlyStatusBar.setValue(indexText["无法更新"] + MixlyArduino.arduinoCliPath + "/arduino-cli.yaml" + "\n" + err, true);
    } else {
        handleHWDir(MixlyUrl.BOARD_CONFIG.folderPath);
    }
});

MixlyArduino.initWithDropdownBox = function () {
    if (typeof (MixlyBU) != "undefined" && MixlyBU.burning) {
        MixlyArduino.burn();
    } else {
        MixlyArduino.upload();
    }
}

MixlyArduino.burn = function () {
    MixlyStatusBar.taChange("output");
    layer.closeAll('page');
    // 当出现串口选择框时，先关闭串口选择框再上传
    document.getElementById('serial-device-form').style.display = 'none';
    layui.use('layer', function () {
        var layer = layui.layer;
        layer.open({
            type: 1,
            title: indexText["烧录中"] + "...",
            content: $('#webusb-flashing'),
            closeBtn: 0,
            success: function () {
                $(".layui-layer-page").css("z-index", "198910151");
            },
            end: function () {
                document.getElementById('webusb-flashing').style.display = 'none';
                $(".layui-layer-shade").remove();
            }
        });
        var portData = $('#select_serial_device option:selected').val();
        if (portData == 'all') {
            var device_values = $.map($('#select_serial_device option'), function (ele) {
                return ele.value;
            });
            MixlyBU.burnByCmd(device_values[0], 0, device_values.length - 1);
        } else {
            //MixlyBU.esptoolBurn(com_data, MixlyBU.ESPTOOL_COMMAND[boardType]);
            MixlyBU.burnByCmd(portData);
        }
    });
}

/**
* @function 编译
* @description 开始一个编译过程
* @return void
*/
MixlyArduino.initCompile = function () {
    var boardType = $('#boards-type option:selected').val();
    if (MixlySerial.object && MixlySerial.object.isOpen) {
        MixlySerial.object.close();
    }
    MixlyArduino.compile(function () { });
}

/**
* @function 编译
* @description 开始一个编译过程
* @return void
*/
MixlyArduino.compile = function (doFunc = function () { }) {
    MixlyStatusBar.taChange("output");
    MixlyArduino.compiling = true;
    MixlyArduino.uploading = false;
    var boardType = $('#boards-type option:selected').val();
    MixlyStatusBar.show(1);
    layui.use('layer', function () {
        var layer = layui.layer;
        layer.open({
            type: 1,
            title: indexText["编译中"] + "...",
            content: $('#webusb-flashing'),
            closeBtn: 0,
            success: function () {
                $(".layui-layer-page").css("z-index", "198910151");
            },
            end: function () {
                MixlyArduino.compiling = false;
                MixlyArduino.uploading = false;
                document.getElementById('webusb-flashing').style.display = 'none';
                $(".layui-layer-shade").remove();
            }
        });
    });
    setTimeout(function () {
        MixlyStatusBar.setValue(indexText["编译中"] + "...\n", true);

        var mainLibPath = "";
        try {
            if (nodeFs.existsSync(MixlyEnv.indexPath + "/libraries/myLib/")
                && nodeFs.statSync(MixlyEnv.indexPath + "/libraries/myLib/").isDirectory()) {
                mainLibPath = MixlyEnv.indexPath + "/libraries/myLib\",\"";
            }
        } catch (e) {
            console.log(e);
        }
        MixlyArduino.runCmd("\""
            + MixlyArduino.arduinoCliPath
            + "/arduino-cli\" compile -b "
            + boardType
            + " --config-file \""
            + MixlyArduino.arduinoCliPath
            + "/arduino-cli.yaml\" --verbose --libraries \""
            + mainLibPath
            + MixlyArduino.arduinoCliPath
            + "/libraries\" --build-path \""
            + MixlyEnv.clientPath
            + "/mixlyBuild\" \""
            + MixlyEnv.clientPath
            + "/testArduino/testArduino.ino\"",
            function () {
                doFunc();
            }
        );
    }, 100);
}

/**
* @function 初始化上传
* @description 关闭已打开的串口，获取当前所连接的设备数，然后开始上传程序
* @return void
*/
MixlyArduino.initUpload = function () {
    var boardType = $('#boards-type option:selected').val();
    if (MixlySerial.object && MixlySerial.object.isOpen) {
        MixlySerial.object.close();
    }
    MixlyArduino.compiling = false;
    MixlyArduino.uploading = true;
    MixlySerial.initPortList("all", ports => {
        var form = layui.form;
        const $devNames = $('#select_serial_device');
        var oldDevice = $('#select_serial_device option:selected').val();
        $devNames.empty();
        _.map(v => {
            if (`${v}` != "undefined") {
                if (`${v}` == oldDevice) {
                    $devNames.append($(`<option value="${v}" selected>${v}</option>`));
                } else {
                    $devNames.append($(`<option value="${v}">${v}</option>`));
                }
            }
        }, ports);
        //$devNames.append('<option value="all">全部</option>');
        form.render();

        var device_num = document.getElementById("select_serial_device").length;
        if (device_num == 0) {
            var layer = layui.layer;
            layer.msg(indexText["无可用设备"] + "!", {
                time: 1000
            });
        } else if (device_num == 1) {
            MixlyArduino.upload();
        } else {
            layui.use(['layer', 'form'], function () {
                var layer = layui.layer;
                layer.open({
                    type: 1,
                    id: "serialSelect",
                    title: indexText["检测到多个串口，请选择："],
                    area: ['350px', '150px'],
                    content: $('#serial-device-form'),
                    closeBtn: 0,
                    success: function (layero) {
                        document.getElementById("serialSelect").style.height = "180px";
                        $(".layui-layer-page").css("z-index", "198910151");
                    },
                    end: function () {
                        document.getElementById('serial-device-form').style.display = 'none';
                        $(".layui-layer-shade").remove();
                    }
                });
            });
        }
    });
}

/**
* @function 上传程序
* @description 通过所选择串口号开始一个上传过程
* @return void
*/
MixlyArduino.upload = function () {
    MixlyStatusBar.taChange("output");
    var boardType = $('#boards-type option:selected').val();
    layer.closeAll('page');
    // 当出现串口选择框时，先关闭串口选择框再上传
    document.getElementById('serial-device-form').style.display = 'none';
    layui.use('layer', function () {
        var layer = layui.layer;
        layer.open({
            type: 1,
            title: indexText["上传中"] + "...",
            content: $('#webusb-flashing'),
            closeBtn: 0,
            success: function () {
                $(".layui-layer-page").css("z-index", "198910151");
            },
            end: function () {
                MixlyArduino.compiling = false;
                MixlyArduino.uploading = false;
                document.getElementById('webusb-flashing').style.display = 'none';
                $(".layui-layer-shade").remove();
            }
        });
        MixlyStatusBar.show(1);
        MixlyStatusBar.setValue(indexText["上传中"] + "...\n", true);
        var device_select_name = $('#select_serial_device option:selected').val();
        MixlySerial.selectedPortName = device_select_name;

        var mainLibPath = "";
        try {
            if (nodeFs.existsSync(MixlyEnv.indexPath + "/libraries/myLib/")
                && nodeFs.statSync(MixlyEnv.indexPath + "/libraries/myLib/").isDirectory()) {
                mainLibPath = MixlyEnv.indexPath + "/libraries/myLib\",\"";
            }
        } catch (e) {
            console.log(e);
        }

        let cmdStr = "";
        if (MixlyArduino.binFilePath !== "") {
            cmdStr = "\""
                + MixlyArduino.arduinoCliPath
                + "/arduino-cli\" -b "
                + boardType
                + " upload -p "
                + device_select_name
                + " --config-file \""
                + MixlyArduino.arduinoCliPath
                + "/arduino-cli.yaml\" --verbose "
                + "-i \"" + MixlyArduino.binFilePath + "\"";
            MixlyArduino.binFilePath = "";
        } else {
            cmdStr = "\""
                + MixlyArduino.arduinoCliPath
                + "/arduino-cli\" compile -b "
                + boardType
                + " --upload -p "
                + device_select_name
                + " --config-file \""
                + MixlyArduino.arduinoCliPath
                + "/arduino-cli.yaml\" --verbose --libraries \""
                + mainLibPath
                + MixlyArduino.arduinoCliPath
                + "/libraries\" --build-path \""
                + MixlyEnv.clientPath
                + "/mixlyBuild\" \""
                + MixlyEnv.clientPath
                + "/testArduino/testArduino.ino\"";
        }
        MixlyArduino.runCmd(cmdStr,
            function () {
                MixlyStatusBar.show(1);
                MixlySerial.refreshPortList("all", function () {
                    MixlySerial.updateSelectBox(MixlySerial.portList);
                    MixlySerial.connectPort();
                });
            }
        );
    });
}

/**
* @function 取消编译或上传
* @description 取消正在执行的编译或上传过程
* @return void
*/
MixlyArduino.cancel = function () {
    if (arduinoShell) {
        try {
            arduinoShell.stdout.end();
            //download_shell.stdin.end();
            //var kill = spawn('kill', [arduinoShell.pid]);
            process.kill(arduinoShell.pid, 'SIGKILL');
            arduinoShell = null;
        } catch (e) {
            arduinoShell = null;
        }
    }
    layer.closeAll('page');
    document.getElementById('webusb-flashing').style.display = 'none';
    if (MixlyArduino.compiling) {
        layer.msg(indexText['已取消编译'], {
            time: 1000
        });
        MixlyStatusBar.addValue("==" + indexText["已取消编译"] + "==\n", true);
    } else if (typeof (MixlyBU) != "undefined" && MixlyBU.burning) {
        layer.msg(indexText['已取消烧录'], {
            time: 1000
        });
        MixlyStatusBar.addValue("==" + indexText["已取消烧录"] + "==\n", true);
        MixlyBU.burning = false;
    } else {
        layer.msg(indexText['已取消上传'], {
            time: 1000
        });
        MixlyStatusBar.addValue("==" + indexText["已取消上传"] + "==\n", true);
    }
    MixlyArduino.compiling = false;
    MixlyArduino.uploading = false;
    MixlyArduino.binFilePath = "";
    MixlyStatusBar.scrollToTheBottom();
}

/**
* @function 检测文件扩展名
* @description 检测文件扩展名是否在扩展名列表内
* @param fileName {String} 文件名
* @param extensionList {Array} 扩展名列表
* @return Boolean
*/
MixlyArduino.checkFileNameExtension = function (fileName, extensionList) {
    if (!fileName) return false;
    let fileNameToLowerCase = fileName;
    let fileNameLen = fileNameToLowerCase.length;
    let fileType = fileNameToLowerCase.substring(fileNameToLowerCase.lastIndexOf("."), fileNameLen);
    if (extensionList.includes(fileType)) {
        return true;
    } else {
        return false;
    }
}

/**
* @function 检测文件扩展名
* @description 检测文件扩展名是否为.c/.cpp或.h/.hpp
* @param fileName {String} 文件名
* @return Boolean
*/
MixlyArduino.isCppOrHpp = function (fileName) {
    return MixlyArduino.checkFileNameExtension(fileName, [".c", ".cpp", ".h", ".hpp"])
}

/**
* @function 检测文件扩展名
* @description 检测文件扩展名是否为.mix/.xml或.ino
* @param fileName {String} 文件名
* @return Boolean
*/
MixlyArduino.isMixOrIno = function (fileName) {
    return MixlyArduino.checkFileNameExtension(fileName, [".mix", ".xml", ".ino"]);
}

/**
* @function 删除给定文件夹下文件
* @description 删除给定文件夹下.c/.cpp和.h/.hpp文件
* @param dir {String} 文件夹路径
* @return void
*/
MixlyArduino.clearDirCppAndHppFiles = function (dir) {
    if (nodeFs.existsSync(dir)) {
        let libDir = nodeFs.readdirSync(dir);
        for (let i = 0; i < libDir.length; i++) {
            if (MixlyArduino.isCppOrHpp(libDir[i])) {
                nodeFs.unlinkSync(dir + libDir[i]);
            }
        }
    }
}

/**
* @function 拷贝文件
* @description 拷贝给定文件夹下.c/.cpp和.h/.hpp文件到目标目录
* @param oldDir {String} 起始文件夹路径
* @param newDir {String} 目标文件夹路径
* @return void
*/
MixlyArduino.copyHppAndCppFiles = function (oldDir, newDir) {
    if (nodeFs.existsSync(oldDir) && nodeFs.existsSync(newDir)) {
        let oldLibDir = nodeFs.readdirSync(oldDir);
        for (let i = 0; i < oldLibDir.length; i++) {
            if (MixlyArduino.isCppOrHpp(oldLibDir[i])) {
                try {
                    nodeFs.copyFileSync(oldDir + oldLibDir[i], newDir + oldLibDir[i]);
                } catch (e) {
                    console.log(e);
                }
            }
        }
    }
}

/**
* @function 运行一个cmd命令
* @description 输入编译或上传的cmd命令
* @param cmd {String} 输入的cmd命令
* @return void
*/
MixlyArduino.runCmd = function (cmd, sucFunc) {
    var code = "";
    if (document.getElementById('tab_arduino').className == 'tabon') {
        code = editor.getValue();
    } else {
        code = Blockly.Arduino.workspaceToCode(Blockly.mainWorkspace) || '';
    }
    if (MixlyEnv.currentPlatform == "win32") {
        try {
            cmd = cmd.replace(/\//g, "\\");
        } catch (e) {
            console.log(e);
        }
    }
    MixlyArduino.clearDirCppAndHppFiles(MixlyEnv.clientPath + "/testArduino/");
    let nowFilePath = MixlyTitle.getFilePath();
    if (nowFilePath) {
        try {
            nowFilePath = nowFilePath.replace(/\\/g, "/");
        } catch (e) {
            console.log(e);
        }
        if (MixlyArduino.isMixOrIno(nowFilePath)) {
            let nowDirPath = nowFilePath.substring(0, nowFilePath.lastIndexOf("/") + 1);
            MixlyArduino.copyHppAndCppFiles(nowDirPath, MixlyEnv.clientPath + "/testArduino/");
        }
    }
    nodeFs.writeFile(MixlyEnv.clientPath + "/testArduino/testArduino.ino", code, 'utf8', function (err) {
        //如果err=null，表示文件使用成功，否则，表示希尔文件失败
        if (err) {
            layer.closeAll('page');
            document.getElementById('webusb-flashing').style.display = 'none';
            layer.msg(indexText['写文件出错了，错误是：'] + err, {
                time: 1000
            });
            MixlyStatusBar.addValue(err, true);
        } else {
            var startTime = Number(new Date());
            arduinoShell = child_process.exec(cmd, { maxBuffer: 4096 * 1000000 }, function (error, stdout, stderr) {
                if (error !== null) {
                    console.log("exec error" + error);
                    if (MixlyArduino.compiling || MixlyArduino.uploading) {
                        //MixlyStatusBar.addValue(error + "\n", true);
                    }
                }
            })

            arduinoShell.stdout.on('data', (data) => {
                if (MixlyArduino.compiling || MixlyArduino.uploading) {
                    /*
                    try {
                        data = decode(iconv.decode(iconv.encode(data, "iso-8859-1"), 'gbk'));
                    } catch (e) {
                        console.log(e);
                    }
                    */
                    if (data.length < 20000) {
                        MixlyStatusBar.addValue(data, true);
                    }
                    //console.log(data)
                    //console.log(data.length)
                }
            });

            arduinoShell.stderr.on('data', (data) => {
                if (MixlyArduino.compiling || MixlyArduino.uploading) {
                    /*
                    try {
                        data = decode(iconv.decode(iconv.encode(data, "iso-8859-1"), 'gbk'));
                    } catch (e) {
                        console.log(e);
                    }
                    */
                    MixlyStatusBar.addValue(data, true);
                }
            });

            arduinoShell.on('close', (code) => {
                var timeCost = parseInt((Number(new Date()) - startTime) / 1000);
                var timeCostSecond = timeCost % 60;
                var timeCostMinute = parseInt(timeCost / 60);
                var timeCostStr = (timeCostMinute ? timeCostMinute + "m" : "") + timeCostSecond + "s";
                if (code == 0) {
                    if (MixlyArduino.compiling) {
                        MixlyStatusBar.addValue("==" + indexText["编译成功"] + "(" + indexText["用时"] + " " + timeCostStr + ")==\n", true);
                        layer.msg(indexText['编译成功'] + '！', {
                            time: 1000
                        });
                    } else if (MixlyArduino.uploading) {
                        MixlyStatusBar.addValue("==" + indexText["上传成功"] + "(" + indexText["用时"] + " " + timeCostStr + ")==\n", true);
                        layer.msg(indexText['上传成功'] + '！', {
                            time: 1000
                        });
                    }
                    sucFunc();
                } else if (code == 1) {
                    //用户终止运行
                } else if (MixlyArduino.uploading) {
                    if (MixlyArduino.compiling) {
                        MixlyStatusBar.addValue("==" + indexText["编译失败"] + "==\n", true);
                    } else {
                        MixlyStatusBar.addValue("==" + indexText["上传失败"] + "==\n", true);
                    }
                }
                MixlyArduino.compiling = false;
                MixlyArduino.uploading = false;
                layer.closeAll('page');
                document.getElementById('webusb-flashing').style.display = 'none';
                MixlyStatusBar.scrollToTheBottom();
            });
        }
    });
}

MixlyArduino.saveBinOrHex = function (writePath) {
    MixlyArduino.writeFile(MixlyEnv.clientPath + "/mixlyBuild", writePath);
}

MixlyArduino.writeFile = function (readPath, writePath) {
    MixlyArduino.compile(function () {
        window.setTimeout(function () {
            layui.use('layer', function () {
                var layer = layui.layer;
                layer.open({
                    type: 1,
                    title: indexText['保存中'] + '...',
                    content: $('#webusb-flashing'),
                    closeBtn: 0,
                    success: function () {
                        $(".layui-layer-page").css("z-index", "198910151");
                        window.setTimeout(function () {
                            try {
                                readPath = readPath.replace(/\\/g, "/");
                                writePath = writePath.replace(/\\/g, "/");
                            } catch (e) {
                                console.log(e);
                            }
                            try {
                                let writeDirPath = writePath.substring(0, writePath.lastIndexOf("."));
                                let writeFileName = writePath.substring(writePath.lastIndexOf("/") + 1, writePath.lastIndexOf("."));
                                let writeFileType = writePath.substring(writePath.lastIndexOf(".") + 1);
                                if (!nodeFs.existsSync(writeDirPath)) {
                                    nodeFs.mkdirSync(writeDirPath);
                                }
                                if (nodeFs.existsSync(writePath)) {
                                    nodeFs.unlinkSync(writePath);
                                }
                                let readBinFilePath = readPath + "/testArduino.ino." + writeFileType;
                                let binFileData = nodeFs.readFileSync(readBinFilePath);
                                nodeFs.writeFileSync(writePath, binFileData);
                                let binFileType = [
                                    ".eep",
                                    ".hex",
                                    ".with_bootloader.bin",
                                    ".with_bootloader.hex",
                                    ".bin",
                                    ".elf",
                                    ".map",
                                    ".partitions.bin",
                                    ".bootloader.bin"
                                ]
                                for (let i = 0; i < binFileType.length; i++) {
                                    let readFilePath = readPath + "/testArduino.ino" + binFileType[i];
                                    let writeFilePath = writeDirPath + "/" + writeFileName + binFileType[i];
                                    if (nodeFs.existsSync(readFilePath)) {
                                        let binData = nodeFs.readFileSync(readFilePath);
                                        nodeFs.writeFileSync(writeFilePath, binData);
                                    }
                                }
                                layer.msg(indexText['保存成功'] + '！', {
                                    time: 1000
                                });
                            } catch (e) {
                                console.log(e);
                                MixlyStatusBar.addValue(e + "\n", true);
                            }
                            layer.closeAll('page');
                        }, 500);
                    },
                    end: function () {
                        document.getElementById('webusb-flashing').style.display = 'none';
                        $(".layui-layer-shade").remove();
                    }
                });
            });
        }, 1000);
    });
}

MixlyArduino.showUploadBox = function (path) {
    try {
        path = path.replace(/\\/g, "/");
    } catch (e) {
        console.log(e);
    }
    let dirPath = path.substring(0, path.lastIndexOf("."));
    try {
        let stat = nodeFs.lstatSync(dirPath);
        if (stat.isDirectory()) {
            path = dirPath + "/" + path.substring(path.lastIndexOf("/") + 1);
        }
    } catch (e) {
        console.log(e);
    }
    layui.use('layer', function () {
        var layer = layui.layer;
        layer.msg(indexText['所打开文件可直接上传'], {
            time: 20000, //20s后自动关闭
            btn: [indexText['取消'], indexText['上传']],
            btnAlign: 'c',
            yes: function () {
                layer.closeAll();
                MixlyArduino.binFilePath = "";
                layer.msg(indexText['已取消上传'], {
                    time: 1000
                });
            },
            btn2: function () {
                layer.closeAll();
                MixlyArduino.uploadWithBinOrHex(path);
            },
            end: function () {
                MixlyArduino.binFilePath = "";
            }
        });
    });

}

MixlyArduino.uploadWithBinOrHex = function (path) {
    layer.closeAll();
    MixlyArduino.binFilePath = path;
    MixlyArduino.initUpload();
}